package tcp

import (
	"fmt"
	"log"
	"net"
	"sync"
	"time"
)

const (
	DefaultReadBufferSize = 4096
	DefaultHeadSize       = 16
)

type sessionHub struct {
	Initializer    func(pipe Pipeline)
	KeepAlive      bool
	ReadBufferSize int
	ReadHeadSize   int
}

func NewSessionHub(initializer func(pipe Pipeline)) *sessionHub {
	return &sessionHub{
		ReadBufferSize: DefaultReadBufferSize,
		ReadHeadSize:   DefaultHeadSize,
		Initializer:    initializer,
		KeepAlive:      true,
	}
}

func (s sessionHub) GetSession(tcpConn net.TCPConn) *Session {
	if s.KeepAlive {
		if err := tcpConn.SetKeepAlive(s.KeepAlive); err != nil {
			log.Println(err)
		}
		if err := tcpConn.SetKeepAlivePeriod(time.Hour * 60); err != nil {
			log.Println(err)
		}
	}

	ses := &Session{
		TCPConn:    tcpConn,
		sessionHub: &s,
		head:       &node{MessageHandler: &HeadHandler{}},
		mu:         new(sync.Mutex),
	}
	ses.tail = ses.head
	s.Initializer(ses)

	ses.sendCtx = &SessionContext{Session: ses}
	ses.readCtx = &SessionContext{Session: ses}
	return ses
}

type Pipeline interface {
	fmt.Stringer
	AddHandlerChain(handlers ...MessageHandler)
}

func (s *Session) AddHandlerChain(handlers ...MessageHandler) {
	for _, handler := range handlers {
		s.tail = s.tail.addNext(handler)
	}
}
